﻿Imports Runa.UI.Compoents
Imports Runa.Foundation.IO
Imports Runa.Foundation
Imports Runa.Scripting.ScriptingHost
Imports Microsoft.Xna.Framework.Content
Imports Runa.Resources.ContentManagers
Imports Runa.UI.Xaml
Imports Runa.Resources.ResourceManager

Namespace Global.Runa.UI.Controls

    Public Class Page
        Inherits Panel

        Public Property Path() As String
        Public Property LayoutXaml() As String

        Public Property IsNavigationPending() As Boolean
            Get
                Return Me.m_IsNavigationPending
            End Get
            Set(value As Boolean)
                If value = False Then
                    Me.Enable = True
                End If
                Me.m_IsNavigationPending = value
            End Set
        End Property

        Private Property Content() As BasicContentManager
        Private Property NavigationParameter() As Tuple(Of Page, Navigation.NavigationContext)

        Private m_IsNavigationPending As Boolean = False

        Public Sub New(ByVal frame As Frame)
            MyBase.New("", Nothing)
            Me.Name = Me.GetType().Name & "_" & BytesToString(Guid.NewGuid().ToByteArray())
            Me.Frame = frame
            Me.Game = frame.Game
            Me.Content = frame.Game.Content
            MyBase.Dispatcher = frame.Dispatcher
        End Sub

        Public Sub New(ByVal Name As String, ByVal frame As Frame)
            MyBase.New(Name, Nothing)
            Me.Frame = frame
            Me.Game = frame.Game
            Me.Content = frame.Game.Content
            MyBase.Dispatcher = frame.Dispatcher
        End Sub

        Public Sub New(ByVal Name As String, ByVal frame As Frame, ByVal path As String)
            Me.New(Name, frame)
            If Name = "" Then
                Me.Name = Me.GetType().Name & "_" & BytesToString(Guid.NewGuid().ToByteArray())
            End If
            Me.Path = path.ToLower()
            Call Me.InitializeCompoentsInternal()
        End Sub

        Public Sub Navigation(ByVal page As Page)
            Me.Navigation(page, New Navigation.NavigationContext())
        End Sub

        Public Sub Navigation(ByVal page As Page, ByVal e As Navigation.NavigationContext)
            Me.NavigationParameter = New Tuple(Of Page, Navigation.NavigationContext)(page, e)
            Me.OnNavigatedFrom(page, e)
            Me.Enable = False
            Me.IsNavigationPending = True
        End Sub

        ''' <summary>
        ''' When navigated to this page, this function will be called.
        ''' </summary>
        ''' <param name="previousPage"></param>
        ''' <param name="e"></param>
        ''' <remarks></remarks>
        Public Overridable Sub OnNavigatedTo(ByVal previousPage As Page, ByVal e As Navigation.NavigationContext)
            Me.NavigationParameter = Nothing
            Me.IsNavigationPending = False
            Return
        End Sub

        ''' <summary>
        ''' When navigated from this page, this function will be called.
        ''' </summary>
        ''' <param name="nextPage"></param>
        ''' <param name="e"></param>
        ''' <remarks></remarks>
        Public Overridable Sub OnNavigatedFrom(ByVal nextPage As Page, ByVal e As Navigation.NavigationContext)
            nextPage.IsNavigationPending = False
            Return
        End Sub

        Public Shared Function LoadFromGameDirectory(ByVal fr As Frame, ByVal path As String, ByVal ifs As GameDirectory, ByVal runtimeErrorHandler As EventHandler(Of RuntimeErrorEventArgs), ByVal compilerErrorEventHandler As EventHandler(Of CompilationErrorEventArgs)) As Page
            Dim name = System.IO.Path.GetFileNameWithoutExtension(path)
            Dim m_scriptPage = New ScriptTask(System.IO.Path.GetFileName(path))
            m_scriptPage.LoadAssembly(GetType(Page).Assembly)
            m_scriptPage.LoadAssembly(GetType(Dictionary(Of String, Texture2DObject)).Assembly)
            m_scriptPage.LoadAssembly(GetType(Texture2DObject).Assembly)
            m_scriptPage.LoadAssembly(GetType(System.Linq.Enumerable).Assembly)
            m_scriptPage.LoadAssembly(GetType(Texture2DObject).Assembly)
            m_scriptPage.LoadAssembly(GetType(SpriteSortMode).Assembly)
            m_scriptPage.LoadAssembly(GetType(Action(Of Int32)).Assembly)
            m_scriptPage.LoadAssembly(GetType(Math).Assembly)
#If WINDOWS Then
            m_scriptPage.LoadAssembly(GetType(System.Speech.TTSWaveSpeaker).Assembly)
#End If
            If runtimeErrorHandler IsNot Nothing Then
                AddHandler m_scriptPage.OnRuntimeError, Sub(sender, e) CType(runtimeErrorHandler, EventHandler(Of RuntimeErrorEventArgs))(sender, e)
            End If
            If compilerErrorEventHandler IsNot Nothing Then
                AddHandler m_scriptPage.OnCompilationError, Sub(sender, e) CType(compilerErrorEventHandler, EventHandler(Of CompilationErrorEventArgs))(sender, e)
            End If
            m_scriptPage.LoadScriptFromGameDirectory(path, ifs)
            m_scriptPage.Execute(String.Format("{0}.new({1}, F, P)", name, ChrW(34) & ChrW(34)), _
                New System.MutableTuple(Of String, Object)("F", fr), _
                New System.MutableTuple(Of String, Object)("P", path))
            Return m_scriptPage.Result
        End Function

        Protected Overridable Sub InitializeCompoents()
        End Sub

        Protected Sub InitializeCompoentsInternal()
            Dim xmlPath = Me.Path.Replace(".rb", ".xaml")
            xmlPath = xmlPath.ToLower().GetRight(Me.Game.Content.RootDirectory.ToLower()).Substring(1)
            If Me.Content.Exists(xmlPath) Then
                If Me.LayoutXaml = "" Then
                    Me.LayoutXaml = Me.Content.LoadAllText(xmlPath)
                    Me.Children.Clear()
                    Dim xml = XElement.Parse(Me.LayoutXaml)
                    Me.LoadFromXaml(xml)
                End If
            End If
            Me.InitializeCompoents()
        End Sub

        Protected Overrides Sub Initialize()
            MyBase.Initialize()
        End Sub

        Public Overrides Sub Update(gameTime As Microsoft.Xna.Framework.GameTime)
            If Me.Animations.Contains(Function(item) item.IsFinished = False) = False And Me.IsNavigationPending Then
                If Me.NavigationParameter IsNot Nothing Then
                    With Me.NavigationParameter
                        Me.Frame.Navigation(.Item1, .Item2)
                    End With
                Else
                    Throw New ArgumentException("Invalid page to navagate to!")
                End If
            End If
            MyBase.Update(gameTime)
        End Sub

        Public Overrides Sub Draw(SpriteBatch As Microsoft.Xna.Framework.Graphics.SpriteBatch)
            MyBase.Draw(SpriteBatch)
        End Sub

    End Class

End Namespace